#pragma once

#include <uuid/uuid.h>
#include <string>
#include <stdexcept>


namespace evm {

using namespace std;

struct uuid {

    uuid() {
        uuid_generate(id);
    }

    uuid(const uuid& u) : str(u.str) {
        uuid_copy(id, u.id);
    }

    uuid(uuid_t id) {
        uuid_copy(this->id, id);
    }

    uuid(const string& str) {
        if (uuid_parse(str.data(), id) < 0)
            throw invalid_argument("invalid uuid string");
        this->str = str;
    }

    operator const string&() const {
        if (str.empty()) {
            char out[37];
            uuid_unparse_lower(id, out);
            str = string(out);
        }
        return str;
    }

    static string to_str() {
        return uuid();
    }

    static bool is_valid(const string& str) {
        uuid_t id;
        return uuid_parse(str.data(), id) == 0;
    }

private:
    uuid_t id;
    mutable string str;

    friend bool operator==(const uuid& u1, const uuid& u2);
    friend bool operator!=(const uuid& u1, const uuid& u2);
};

inline bool operator==(const uuid& u1, const uuid& u2) {
    return uuid_compare(u1.id, u2.id) == 0;
}

inline bool operator!=(const uuid& u1, const uuid& u2) {
    return uuid_compare(u1.id, u2.id) != 0;
}

}
